package cn.htsyb.synergy.security.controller;

import cn.htsyb.synergy.model.ApiResult;
import cn.htsyb.synergy.orm.constant.DeleteMode;
import cn.htsyb.synergy.orm.jpa.criterion.OrderExpress;
import cn.htsyb.synergy.orm.jpa.criterion.QueryExpress;
import cn.htsyb.synergy.orm.jpa.model.param.PageParam;
import cn.htsyb.synergy.security.bean.param.SecurityRoleParam;
import cn.htsyb.synergy.security.entity.SecurityRole;
import cn.htsyb.synergy.security.service.ISecurityRoleService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
 * 角色 接口
 * codeMaker at 2020-07-14
 * @author lakeside hubin_yuan.410@hotmail.com
 * @since 2020-07-14
 */
@Slf4j(topic = "security")
@RestController(value = "SecurityRoleRestController")
@RequestMapping(value = {"/security/role"} )
@Tag(name = "SecurityRoleRestController",description ="角色接口" )
public class SecurityRoleRestController {
    @Autowired
    protected ISecurityRoleService securityRoleService;
    ObjectMapper objectMapper = new ObjectMapper();
    /**
    * 默认排序
    * @return
    */
    private  List<OrderExpress> defaultOrderBy(){
        return new ArrayList<OrderExpress>(){{
            this.add(new OrderExpress("id" , OrderExpress.Direction.DESC));
        }} ;
    }
    /**
    * 添加【我的】条件
    * @return
    */
    private  List<QueryExpress> addMineCriterion(List<QueryExpress> searchBys){
        //searchBys.add(new QueryExpress("created_by", OperatorEnum.EQ,SecurityContextUtil.getCurrentAuthUserId()));
        return searchBys;
    }
    @Operation(summary  = "统计数量查询" )
    @GetMapping(value = "/count" )
    public ApiResult<Long> countSearch(SecurityRoleParam securityRoleParam) {
        try {
            Long  countSize = securityRoleService.countAll(addMineCriterion(securityRoleParam.searchCriterion()), securityRoleParam.filterCriterion());
            return ApiResult.instance(countSize);
        } catch (Exception ex) {
            log.error("统计数量查询" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }

    @Operation(summary = "获取对象信息" )
    @GetMapping(value = "/{idArr}" )
    public ApiResult<SecurityRole> findById(@PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr) {
        try {
            if(idArr.size()==1){
                SecurityRole securityRole=securityRoleService.findById (idArr.get(0));
                Assert.notNull(securityRole ,"实体对象不存在");
                return new ApiResult(securityRole);
            }else{
                List<SecurityRole> securityRoleList=  securityRoleService.findAllByIds(idArr);
                return new ApiResult(securityRoleList);
            }
        } catch (Exception ex) {
            log.error("获取对象信息出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }

    @Operation(summary = "分页查询信息" )
    @GetMapping(value = "/page" )
    @ResponseBody
    public ApiResult<Page<SecurityRole>> pageSearch(PageParam pageParam, SecurityRoleParam securityRoleParam) {
        try {
            List<OrderExpress> orderBys= OrderExpress.parseOrderParam( pageParam.getOrder());
            if(CollectionUtils.isEmpty(orderBys)){orderBys=defaultOrderBy();}
            Page<SecurityRole> pageResult = securityRoleService.findAllPage(
                    addMineCriterion(securityRoleParam.searchCriterion()),
                    securityRoleParam.filterCriterion(),orderBys,pageParam);
            return ApiResult.instance(pageResult);
        } catch (Exception ex) {
            log.error("分页查询实体出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }

    @Operation(summary = "列表查询信息" )
    @GetMapping(value = "/list" )
    public ApiResult<Collection<SecurityRole>> listSearch(SecurityRoleParam securityRoleParam) {
        try {
            Collection<SecurityRole> listResult = securityRoleService.findAllList(
                    addMineCriterion(securityRoleParam.searchCriterion()),
                    securityRoleParam.filterCriterion(),defaultOrderBy());
            return new ApiResult(listResult);
        } catch (Exception ex) {
            log.error("查询实体列表出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
    @PreAuthorize("hasAnyAuthority({'security:role:add','security:role:edit'})")
    @Operation(summary = "批量保存实体信息（全量插入）" , description = "批量保存实体信息（更新面向实体，全量插入）" )


    @PostMapping(value = "/save" )
    public ApiResult<?> saveBatch( @RequestBody @NotNull JsonNode filedJsonNode) {
        try {
            if(filedJsonNode.isArray()){
                List<SecurityRole> securityRoleList=objectMapper.readValue(filedJsonNode.toString(),new TypeReference<List<SecurityRole>>() {});
                return ApiResult.instance(securityRoleService.saveAllEntity(securityRoleList));
            }else{
                SecurityRole securityRole=objectMapper.readValue(filedJsonNode.toString(),SecurityRole.class);
                return ApiResult.instance(securityRoleService.saveEntity(securityRole));
            }
        } catch (Exception ex) {
            log.error("保存实体信息出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
    @PreAuthorize("hasAuthority('security:role:edit')")
    @Operation(summary = "批量更新实体部分字段信息" , description = "批量更新实体的字段信息(更新面向字段，未传字段不更新))" )

    @PutMapping(value = "/{idArr}" )
    public ApiResult<List<SecurityRole>> patchBatch(
            @PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr,
            @NotNull @RequestBody JsonNode filedJsonNode) {
        try {
            Assert.isTrue( !filedJsonNode.has("id"),"更新字段中不能存在主键编号字段");
            Assert.isTrue( !filedJsonNode.isArray(),"不能使用数组设置更新字段");
            List<SecurityRole> securityRoleList=  securityRoleService.findAllByIds(idArr);
            for (SecurityRole securityRole:securityRoleList) {
                objectMapper.readerForUpdating(securityRole).readValue(filedJsonNode);
            }
                securityRoleService.saveAllEntity(securityRoleList);
            return ApiResult.instance(securityRoleList);
        } catch (Exception ex) {
            log.error("更新实体字段信息出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
    @PreAuthorize("hasAuthority('security:role:del')")
    @Operation(summary = "实体删除" )
    @DeleteMapping(value = "/{idArr}" )
    public ApiResult<List<String>> deleteBatch(
            @PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr,
            @RequestParam(required = false, defaultValue = "logical" ) @Parameter(description = "删除模式", required = true) DeleteMode deleteMode) {
        try {
            securityRoleService.deleteByIds(idArr,deleteMode);

            return ApiResult.instance(idArr);
        } catch (Exception ex) {
            log.error("实体删除出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
}
